﻿package {
	import flash.display.*;
	import flash.text.*;
	import flash.events.*;
	import flash.external.*;
	import flash.geom.*;
	import flash.net.*;
	import flash.system.*;
	import flash.filters.*;
	import json.*;
	import caurina.transitions.Tweener;
	public class Pie extends Sprite {
		private var stageW:Number;
		private var stageH:Number;
		private var pie:Object;
		//主绘图层
		private var main:Sprite;
		//Tip层
		private var tip:Tip;
		//标记格式
		private var tagFormat:TextFormat;
		//首次运行
		private var one:Boolean = true;
		public function Pie() {
			stage.scaleMode = "noScale";
			stage.align = "topLeft";
			stage.addEventListener(Event.RESIZE, resizeHd);
			//添加主绘图层
			main = new Sprite();
			addChild(main);
			//添加Tip层
			tip = new Tip(100, 0);
			addChild(tip);
			//
			init();
		}
		private function init():void {
			var data:String = cV("data");
			if (data) {
				//O.o(str);
				parseData(data);
			} else {
				var url:String = cV("url");
				if (!url) {
					url = "pie_data.txt";
				}
				var dataLoader:URLLoader = new URLLoader();
				dataLoader.load(new URLRequest(url));
				dataLoader.addEventListener(IOErrorEvent.IO_ERROR, errorHd);
				dataLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errorHd);
				dataLoader.addEventListener(Event.COMPLETE, completeHd);
			}
		}
		private function errorHd(e:Event):void {

		}
		private function completeHd(e:Event):void {
			var str:String = e.target.data;
			if (str) {
				//O.o(str);
				//过滤注释行
				str = str.replace(/\/\/.*\s/g,"");
				//过滤回车换行
				str = str.replace(/\n|\r/g,"");
				//O.o(str);
				parseData(str);
			}
		}
		//解析JSON数据
		private function parseData(str:String):void {
			try {
				pie = new JSONDecoder(str).getValue();
				//
				//O.o(pie.max);
				layout();
			} catch (e:Error) {
				O.o(e);
			}
		}
		private function resizeHd(e:Event):void {
			one = false;
			layout();
		}
		//开始布局绘图
		private function layout():void {
			stageW = stage.stageWidth;
			stageH = stage.stageHeight;
			//
			drawAll();
		}
		private function clearAll():void {
			while (main.numChildren) {
				main.removeChildAt(0);
			}
		}
		private function drawAll():void {
			//清除所有
			clearAll();
			//画饼图
			tagFormat = gF("Verdana",11,parseInt(pie.color.replace(/#/g, "0x")));
			//O.o(pie.ltrb);
			var left:Number = pie.ltrb[0];
			var top:Number = pie.ltrb[1];
			var right:Number = pie.ltrb[2];
			var bottom:Number = pie.ltrb[3];
			//
			var bx:Number = left;
			var by:Number = top;
			var bw:Number = stageW - left - right;
			var bh:Number = stageH - top - bottom;
			//半径及圆心
			var cr:Number;
			var cx:Number;
			var cy:Number;
			if ( bw > bh) {
				cr = bh * 0.5;
				cx = bx + cr;
				cy = by + cr;
			} else {
				cr = bw * 0.5;
				cx = bx + cr;
				cy = by + bh * 0.5;
			}
			//饼图背景
			var bg:Sprite = new Sprite();
			bg.graphics.beginFill(0xf5f5f5);
			bg.graphics.drawCircle(cx, cy, cr);
			bg.graphics.endFill();
			bg.filters = tip.gS(0, 0.5);
			main.addChild(bg);
			//=================================================
			//饼图扇形
			var list:Array = pie.list;
			//区块总数
			var ll:int = list.length;
			//减去最小数
			var min:Number = pie.min;
			if (isNaN(min)) {
				min = 0;
			}
			//求和总值---------------------
			var total:Number = 0;
			for (var i:int = 0; i<ll; i++) {
				var tn:Number = list[i][2];
				if (isNaN(tn)) {
					tn = 0;
				}
				list[i][2] = tn;
				total += tn - min;
			}
			//决定最大值
			var max:Number = pie.max;
			if (isNaN(max) || max< total) {
				max = total;
				pie.max = max;
			}
			//画扇形-------------------------
			var sectors:Sprite = new Sprite();
			//初始位置
			var degree:Number = 0;
			//实际总分
			var score:Number = 0;
			for (var j:int = 0; j < ll; j++) {
				var sector:Sprite = new Sprite();
				sector.buttonMode = true;
				score += (list[j][2] - min);
				//算出百分比
				var per:Number = (list[j][2] - min)/max;
				//保存显示比值和百分比串备用
				list[j][4] = per;
				if (pie.show_value) {
					if (pie.show_average) {
						//显示相对增量
						var increment:Number = list[j][2] - pie.show_average;
						if (increment > 0) {
							list[j][5] = " (+" + increment + ")";
						} else {
							list[j][5] = " (" + increment + ")";
						}
					} else {
						list[j][5] = " (" + list[j][2] + ")";
					}
				} else {
					list[j][5] = " (" + Math.round(per*10000)/100 + "%)";
				}
				//
				var r:Number = cr;
				var c:Number = parseInt(list[j][1].replace(/#/g, "0x"));
				var a:Number = 1;
				var d:Number = Math.round(360*per);
				//修正最后一次位置
				if (j == ll - 1) {
					if (score == max) {
						d = 360 - degree;
					}
				}
				var n:Number = degree;
				degree += d;
				drawSector(sector, r, c, a, d, n);
				sector.name = "sector__" + j;
				sector.addEventListener(MouseEvent.CLICK, clickHd);
				sector.addEventListener(MouseEvent.MOUSE_OVER, overHd);
				sector.addEventListener(MouseEvent.MOUSE_OUT, outHd);
				sectors.addChild(sector);
			}
			sectors.x = cx;
			sectors.y = cy;
			main.addChild(sectors);
			//=====================================================
			//环绕信息区
			if (pie.show_title) {
				var titles:Sprite = new Sprite();
				for (var ti:int = 0; ti < ll; ti ++) {
					//取得扇形边弧的中心点位置===================
					//取得当前扇形
					var theSector:Sprite = sectors.getChildByName("sector__" + ti) as Sprite;
					//弧中心度数
					var theDegree:Number = Math.round(360*pie.list[ti][4])/2 + theSector.rotation;
					var ther:Number = cr + 6;
					var thex:Number = cx+ther*Math.cos(theDegree*Math.PI/180);
					var they:Number = cy+ther*Math.sin(theDegree*Math.PI/180);
					var align:String = "left";
					if (thex < cx) {
						align = "right";
					}
					var valign:String = "middle";
					if (they < (cy - cr*0.5)) {
						valign = "bottom";
					} else if (they > (cy + cr*0.5)) {
						valign = "top";
					}
					var tt:TextField = getLabel(list[ti][0], thex, they, tagFormat, align, valign);
					titles.addChild(tt);
					//画连接线

				}
				main.addChild(titles);
			}
			//=====================================================
			//右边信息区
			if (pie.show_msg) {
				var mr:Number = cr*0.2;
				var mh:Number = 24;
				var mw:Number = 12;
				var mx:Number = left + cr * 2 + mr;
				var msg:Sprite = new Sprite();
				for (var mi:int = 0; mi < ll; mi ++) {
					var mc:Number = parseInt(list[mi][1].replace(/#/g, "0x"));
					var my:Number = mi * mh + mh/2;
					var dot:Sprite = new Sprite();
					dot.graphics.beginFill(mc);
					dot.graphics.drawRect(mx, my - mw/2, mw, mw);
					dot.graphics.endFill();
					msg.addChild(dot);
					var str:String = list[mi][0];
					if (pie.show_percent) {
						str += list[mi][5];
					}
					var mt:TextField = getLabel(str, mx + mw + 5, my - 3, tagFormat, "left");
					msg.addChild(mt);
				}
				msg.y = top + (bh - mh * ll)/2;
				main.addChild(msg);
			}
		}
		//画单个扇形
		private function drawSector(sector:Sprite, r:Number, c:Number, a:Number, d:Number, n:Number) {
			//
			if (pie.color_depth) {
				var matr:Matrix = new Matrix();
				matr.createGradientBox(2*r, 2*r, 0, -r, -r);
				//var dcolor:Number = getDepthColor(c, pie.color_depth);
				var dcolor:Number = depthColor(c, pie.color_depth);
				//O.o(c+"|"+dcolor);
				sector.graphics.beginGradientFill(GradientType.RADIAL, [c, dcolor], [1, 1], [127, 255], matr, SpreadMethod.PAD);
			} else {
				sector.graphics.beginFill(c, a);
			}
			//边框
			sector.graphics.lineStyle(1, 0xffffff, .5);
			//去边
			sector.graphics.lineTo(r, 0);
			//画弧
			for (var i:Number = 0; i<=d; i++) {
				var bx:Number = r*Math.cos(i*Math.PI/180);
				var by:Number = r*Math.sin(i*Math.PI/180);
				sector.graphics.lineTo(bx, by);
			}
			//回原点
			sector.graphics.lineTo(0, 0);
			sector.graphics.endFill();
			//旋转
			sector.rotation = n;
		}
		//
		private function clickHd(e:MouseEvent):void {
			var a:Array = e.target.name.split("__");
			var i:Number = a[1];
			var sector:Sprite = e.target as Sprite;
			if (sector.x || sector.y) {
				moveTo(sector, 0, 0);
			} else {
				var d:Number = Math.round(360*pie.list[i][4])/2 + sector.rotation;
				var r:Number = pie.move_length;
				if (isNaN(r)) {
					r = 10;
				}
				moveTo(sector, r*Math.cos(d*Math.PI/180), r*Math.sin(d*Math.PI/180));
			}
		}
		private function moveTo(sp:Sprite, tx:Number, ty:Number):void {
			Tweener.addTween(sp, {x:tx, y:ty, time:0.2, transition:"linear"});
		}
		//
		private function overHd(e:MouseEvent):void {
			var sector:Sprite = e.target as Sprite;
			sector.alpha = 0.8;
			//
			var i:int = parseInt(e.target.name.split("__")[1]);
			var str:String;
			if (pie.list[i][3]) {
				str = pie.list[i][3];
			} else {
				str = pie.list[i][0];
			}
			if (pie.show_percent) {
				str += pie.list[i][5];
			}
			tip.show(str);
		}
		private function outHd(e:MouseEvent):void {
			var sector:Sprite = e.target as Sprite;
			sector.alpha = 1;
			//
			tip.hide();
		}
		//新建标记
		private function getLabel(s:String, tx:int, ty:int, tf:TextFormat, align:String = "center", valign:String = "middle"):TextField {
			var label:TextField = new TextField();
			label.selectable = false;
			label.mouseEnabled = false;
			label.autoSize = "left";
			label.htmlText = s;
			label.setTextFormat(tf);
			if (align == "left") {
				label.x = tx;
			} else if (align == "right") {
				label.x = tx - label.textWidth;
			} else {
				label.x = tx - label.textWidth/2;
			}
			if (valign == "top") {
				label.y = ty;
			} else if (valign == "bottom") {
				label.y = ty - label.textHeight;
			} else {
				label.y = ty - label.textHeight/2;
			}
			return label;
		}
		//标记格式
		private function gF(font:String = "Verdana", size:Number = 12, color:Number = 0):TextFormat {
			var tf:TextFormat = new TextFormat();
			tf.font = font;
			tf.size = size;
			tf.color = color;
			return tf;
		}
		//读取传入参数
		public function cV(str:String):String {
			return this.root.loaderInfo.parameters[str];
		}
		//色彩转换
		function getDepthColor(c:Number, depth:Number):Number {
			var red:Number = (c >> 16 & 0xFF);
			var green:Number = (c >> 8 & 0xFF);
			var blue:Number = (c & 0xFF);
			//
			var hsb:Array = rgbtohsb(red, green, blue);
			//H色相、S饱和度、B明度
			//S和B的取值都是百分比，H的取值单位是色环的度数(0-360)
			//调节亮度
			var ch:Number = hsb[0];
			var cs:Number = hsb[1];
			var cb:Number = hsb[2]*depth;
			var rgb:Array = hsbtorgb(ch, cs, cb);
			//
			c = rgb[0]<<16 | rgb[1]<<8 | rgb[2];
			return c;
		}
		function depthColor(c:Number, depth:Number):Number {
			var red:Number = (c >> 16 & 0xFF)*depth;
			var green:Number = (c >> 8 & 0xFF)*depth;
			var blue:Number = (c & 0xFF)*depth;
			return red<<16 | green<<8 | blue;
		}
		function hsbtorgb(hue:Number,saturation:Number,brightness:Number):Array {
			var red:Number, green:Number, blue:Number;
			hue%=360;
			if (brightness==0) {
				return [0,0,0];
			}
			saturation/=100;
			brightness/=100;
			hue/=60;
			var i = Math.floor(hue);
			var f = hue-i;
			var p = brightness*(1-saturation);
			var q = brightness*(1-(saturation*f));
			var t = brightness*(1-(saturation*(1-f)));
			switch (i) {
				case 0 :
					red=brightness;
					green=t;
					blue=p;
					break;
				case 1 :
					red=q;
					green=brightness;
					blue=p;
					break;
				case 2 :
					red=p;
					green=brightness;
					blue=t;
					break;
				case 3 :
					red=p;
					green=q;
					blue=brightness;
					break;
				case 4 :
					red=t;
					green=p;
					blue=brightness;
					break;
				case 5 :
					red=brightness;
					green=p;
					blue=q;
					break;
			}
			red=Math.round(red*255);
			green=Math.round(green*255);
			blue=Math.round(blue*255);
			return [red,green,blue];
		}

		function rgbtohsb(red:Number,green:Number,blue:Number):Array {
			var min=Math.min(Math.min(red,green),blue);
			var brightness=Math.max(Math.max(red,green),blue);
			var delta=brightness-min;
			var saturation=(brightness == 0) ? 0 : delta/brightness;
			var hue;
			if (saturation == 0) {
				hue=0;
			} else {
				if (red == brightness) {
					hue=(60*(green-blue))/delta;
				} else if (green == brightness) {
					hue=120+(60*(blue-red))/delta;
				} else {
					hue=240+(60*(red-green))/delta;
				}
				if (hue<0) {
					hue+=360;
				}
			}
			saturation*=100;
			brightness=(brightness/255)*100;
			return [hue,saturation,brightness];
		}

	}
}